home *** CD-ROM | disk | FTP | other *** search
- /*
- * Copyright 1991, 1992, 1993, 1994, Silicon Graphics, Inc.
- * All Rights Reserved.
- *
- * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
- * the contents of this file may not be disclosed to third parties, copied or
- * duplicated in any form, in whole or in part, without the prior written
- * permission of Silicon Graphics, Inc.
- *
- * RESTRICTED RIGHTS LEGEND:
- * Use, duplication or disclosure by the Government is subject to restrictions
- * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
- * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
- * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
- * rights reserved under the Copyright Laws of the United States.
- */
- /*
- * model/room drawing stuff
- * Yossi Friedman, July 1988
- */
-
- #include <stdio.h>
- #include <gl.h>
- #include <math.h>
-
- #include "config.h"
- #include "newton.h"
-
- /*
- * constants
- */
- #define SURF_TOL (1. + 2. * (TOLERANCE - 1.))
- #define SHADOW_TOL (1. + 1. * (TOLERANCE - 1.))
- #define DIST (5. * HEIGHT)
-
- /* RADIUS is the radius of the bounding circle of the room */
- #define RADIUS (HEIGHT * (M_SQRT2 + 0.50))
-
- #define GREY 18 /* wall color for bermuda mode */
-
- static unsigned short halftone[] = { /* shadow blending pattern */
- 0x5555, 0xaaaa, 0x5555, 0xaaaa,
- 0x5555, 0xaaaa, 0x5555, 0xaaaa,
- 0x5555, 0xaaaa, 0x5555, 0xaaaa,
- 0x5555, 0xaaaa, 0x5555, 0xaaaa
- };
- #define HALFTONE 1
-
-
-
-
- /*
- * state variables
- */
- static int new_M; /* was M changed since last frame? */
- static int lighting; /* is the lighting model truned on? */
-
-
-
-
- /*
- * lighting model descriptors
- */
- static float wall_material[MAX_LIGHTING_SIZE] = { WALL_MATERIAL };
- static int wall_material_size = WALL_MATERIAL_SIZE;
-
- #define WALL_MATERIAL_INDEX (MODEL_MATERIAL_INDEX + 1)
-
- static float model_lmodel[MAX_LIGHTING_SIZE] = { MODEL_LMODEL };
- static int model_lmodel_size = MODEL_LMODEL_SIZE;
-
- static float light[MAX_LIGHTING_SIZE] = { POSITION, LIGHT_VECTOR, 0., LMNULL };
- static int light_size = 6;
-
-
-
- /*
- * a vector pointing from the origin INTO the light source. The _M
- * contains the light vector in the MODELING (room) coordinate system, and
- * the _V -- in the VIEWING coordinate system. The idea is that the _V
- * stays fixed.
- */
- static float light_vec_V[3] = { LIGHT_VECTOR };
- static float light_vec_M[3] = { LIGHT_VECTOR };
-
- void lighting_on();
- void lighting_off();
-
- /*
- * pinball mode variables, miscellaneaous variables
- */
- static float red1 = RED1;
- static float red2 = RED2;
- static float green1 = GREEN1;
- static float green2 = GREEN2;
- static float blue1 = BLUE1;
- static float blue2 = BLUE2;
-
- static float vel_factor = 0.;
-
-
- /*
- * HEDGEHOG macro, for drawing normals (an essential debugging feature)
- */
- #ifdef HEDGEHOG
- # define draw_norm(v, norm) \
- /* float v[3], norm[3] */ \
- do { \
- float vert[3]; \
- if (mode == COLOR_MAP) \
- color(BLUE); \
- else \
- RGBcolor(0, 0, 200); \
- bgnline(); \
- v3f(v); \
- vert[0] = v[X] + 10.0*norm[X]; \
- vert[1] = v[Y] + 10.0*norm[Y]; \
- vert[2] = v[Z] + 10.0*norm[Z]; \
- v3f(vert); \
- if (mode == COLOR_MAP) \
- color(YELLOW); \
- else \
- RGBcolor(200, 200, 0); \
- vert[0] += 5.0*norm[X]; \
- vert[1] += 5.0*norm[Y]; \
- vert[2] += 5.0*norm[Z]; \
- v3f(vert); \
- endline(); \
- } while (0)
- #else /* HEDGEHOG*/
- # define draw_norm(v, norm) do /* nothing */; while (0)
- #endif /* HEDGEHOG */
-
-
-
-
- initialize_draw()
- {
- int n, i, j;
-
- /* initialize the relevant parts of the wall array */
-
- # define wall_verts(WALL, x1,y1,z1, x2,y2,z2, x3,y3,z3, x4,y4,z4) \
- wall[WALL].real_v[0][X] = 0. x1 HEIGHT; \
- wall[WALL].real_v[0][Y] = 0. y1 HEIGHT; \
- wall[WALL].real_v[0][Z] = 0. z1 HEIGHT; \
- \
- wall[WALL].real_v[1][X] = 0. x2 HEIGHT; \
- wall[WALL].real_v[1][Y] = 0. y2 HEIGHT; \
- wall[WALL].real_v[1][Z] = 0. z2 HEIGHT; \
- \
- wall[WALL].real_v[2][X] = 0. x3 HEIGHT; \
- wall[WALL].real_v[2][Y] = 0. y3 HEIGHT; \
- wall[WALL].real_v[2][Z] = 0. z3 HEIGHT; \
- \
- wall[WALL].real_v[3][X] = 0. x4 HEIGHT; \
- wall[WALL].real_v[3][Y] = 0. y4 HEIGHT; \
- wall[WALL].real_v[3][Z] = 0. z4 HEIGHT; \
- \
- wall[WALL].surf_v[0][X] = 0. x1 SURF_TOL * HEIGHT; \
- wall[WALL].surf_v[0][Y] = 0. y1 SURF_TOL * HEIGHT; \
- wall[WALL].surf_v[0][Z] = 0. z1 SURF_TOL * HEIGHT; \
- \
- wall[WALL].surf_v[1][X] = 0. x2 SURF_TOL * HEIGHT; \
- wall[WALL].surf_v[1][Y] = 0. y2 SURF_TOL * HEIGHT; \
- wall[WALL].surf_v[1][Z] = 0. z2 SURF_TOL * HEIGHT; \
- \
- wall[WALL].surf_v[2][X] = 0. x3 SURF_TOL * HEIGHT; \
- wall[WALL].surf_v[2][Y] = 0. y3 SURF_TOL * HEIGHT; \
- wall[WALL].surf_v[2][Z] = 0. z3 SURF_TOL * HEIGHT; \
- \
- wall[WALL].surf_v[3][X] = 0. x4 SURF_TOL * HEIGHT; \
- wall[WALL].surf_v[3][Y] = 0. y4 SURF_TOL * HEIGHT; \
- wall[WALL].surf_v[3][Z] = 0. z4 SURF_TOL * HEIGHT; \
- \
- vec_op(wall[WALL].surf_e[0], \
- wall[WALL].surf_v[1], -, wall[WALL].surf_v[0]); \
- \
- vec_op(wall[WALL].surf_e[1], \
- wall[WALL].surf_v[2], -, wall[WALL].surf_v[1]); \
- \
- vec_op(wall[WALL].surf_e[2], \
- wall[WALL].surf_v[3], -, wall[WALL].surf_v[2]); \
- \
- vec_op(wall[WALL].surf_e[3], \
- wall[WALL].surf_v[0], -, wall[WALL].surf_v[3])
-
- wall_verts(WALL_TOP, +,+,-, +,+,+, -,+,+, -,+,-);
- wall_verts(WALL_BOTTOM, +,-,-, -,-,-, -,-,+, +,-,+);
- wall_verts(WALL_RIGHT, +,-,+, +,+,+, +,+,-, +,-,-);
- wall_verts(WALL_LEFT, -,-,+, -,-,-, -,+,-, -,+,+);
- wall_verts(WALL_FRONT, -,+,+, +,+,+, +,-,+, -,-,+);
- wall_verts(WALL_BACK, -,+,-, -,-,-, +,-,-, +,+,-);
- #undef wall_verts
-
- wall[WALL_TOP] .axis = Y;
- wall[WALL_TOP] .sign = 1.;
- wall[WALL_TOP] .real_norm[X] = 0.;
- wall[WALL_TOP] .real_norm[Y] = -1.;
- wall[WALL_TOP] .real_norm[Z] = 0.;
-
- wall[WALL_BOTTOM].axis = Y;
- wall[WALL_BOTTOM].sign = -1.;
- wall[WALL_BOTTOM].real_norm[X] = 0.;
- wall[WALL_BOTTOM].real_norm[Y] = 1.;
- wall[WALL_BOTTOM].real_norm[Z] = 0.;
-
- wall[WALL_RIGHT] .axis = X;
- wall[WALL_RIGHT] .sign = 1.;
- wall[WALL_RIGHT] .real_norm[X] = -1.;
- wall[WALL_RIGHT] .real_norm[Y] = 0.;
- wall[WALL_RIGHT] .real_norm[Z] = 0.;
-
- wall[WALL_LEFT] .axis = X;
- wall[WALL_LEFT] .sign = -1.;
- wall[WALL_LEFT] .real_norm[X] = 1.;
- wall[WALL_LEFT] .real_norm[Y] = 0.;
- wall[WALL_LEFT] .real_norm[Z] = 0.;
-
- wall[WALL_FRONT] .axis = Z;
- wall[WALL_FRONT] .sign = 1.;
- wall[WALL_FRONT] .real_norm[X] = 0.;
- wall[WALL_FRONT] .real_norm[Y] = 0.;
- wall[WALL_FRONT] .real_norm[Z] = -1.;
-
- wall[WALL_BACK] .axis = Z;
- wall[WALL_BACK] .sign = -1.;
- wall[WALL_BACK] .real_norm[X] = 0.;
- wall[WALL_BACK] .real_norm[Y] = 0.;
- wall[WALL_BACK] .real_norm[Z] = 1.;
-
- for (n = 0; n < 6; n++)
- for (i = 0; i < 4; i++)
- for (j = 0; j < 4; j++)
- wall[n].shadow[i][j] = ident_matrix[i][j];
-
- /* define the pattern used for shadows */
- defpattern(HALFTONE, 16, halftone);
- }
-
-
- long
- open_model_window(char *title)
- {
- long wid;
-
- keepaspect(5, 4);
-
- foreground();
-
- wid = winopen(title);
- if (getgdesc(GD_BITS_NORM_SNG_RED) == 0)
- {
- system("inform 'Your system must support RGB mode to run newton'");
- exit(1);
- }
- if (getgdesc(GD_BITS_NORM_ZBUFFER) == 0)
- {
- system("inform 'Your system must have a z-buffer to run newton'");
- exit(1);
- }
-
- keepaspect(5, 4);
- winconstraints();
- wintitle("Newton Model");
-
- doublebuffer();
- if (mode == RGB)
- RGBmode();
- else
- cmode();
- gconfig();
-
- zbuffer(TRUE);
-
- #ifdef HAS_CZCLEAR
- zfunction(ZF_GEQUAL);
- /* lsetdepth(0x7fffff, 0x2000); */
- lsetdepth((getgdesc(GD_ZMAX)), 0x2000);
- #else /* HAS_CZCLEAR */
- setdepth(0xc000, 0x3fff);
- #endif /* HAS_CZCLEAR */
-
- lmdef(DEFLMODEL, 1, model_lmodel_size, model_lmodel);
- lmdef(DEFLIGHT, 1, light_size, light);
- lmdef(DEFMATERIAL, WALL_MATERIAL_INDEX, wall_material_size, wall_material);
-
- /* set the light vector */
- normalize(light_vec_V);
- apply(light_vec_M, light_vec_V, M_inv);
-
- lighting_off();
- lighting_on();
- return(wid);
- }
-
-
- void
- close_model_window(long wid)
- {
- lighting_off();
- winclose(wid);
- }
-
-
- #ifdef CONFIG_FILE
-
- initialize_config()
- {
- FILE *fp;
- char line[200], *p;
- int n, q;
- float f;
-
- fp = fopen(model_config, "r");
- if (fp == NULL) {
- fprintf(stderr, "newton: Could not open ");
- if (model_config[0] == '/')
- fprintf(stderr, "%s\n", model_config);
- else
- fprintf(stderr, "%s/%s\n", cwd(), model_config);
- my_exit(1);
- }
- while (fgets(line, 200, fp) != NULL)
- switch (line[0]) {
- case '\n':
- case '#':
- continue;
-
- case 'v':
- sscanf(line + 1, "%f", &vel_factor);
- break;
-
- case 'r':
- sscanf(line + 1, "%f %f", &red1, &red2);
- break;
-
- case 'g':
- sscanf(line + 1, "%f %f", &green1, &green2);
- break;
-
- case 'b':
- sscanf(line + 1, "%f %f", &blue1, &blue2);
- break;
-
- case 'l':
- p = line + 1;
- for (n = 0; sscanf(p, "%f%n", &f, &q) == 1; p += q) {
- if (n == MAX_LIGHTING_SIZE) {
- fprintf(stderr, "newton: Light too big\n");
- my_exit(1);
- }
- light[n++] = f;
- }
- if (light[0] == POSITION) {
- light_vec_V[X] = light[1];
- light_vec_V[Y] = light[2];
- light_vec_V[Z] = light[3];
- }
- light_size = n;
- break;
-
- case 'L':
- p = line + 1;
- for (n = 0; sscanf(p, "%f%n", &f, &q) == 1; p += q) {
- if (n == MAX_LIGHTING_SIZE) {
- fprintf(stderr, "newton: Lighting model too big\n");
- my_exit(1);
- }
- model_lmodel[n++] = f;
- }
- model_lmodel_size = n;
- break;
-
- case 'J':
- p = line + 1;
- for (n = 0; sscanf(p, "%f%n", &f, &q) == 1; p += q) {
- if (n == MAX_LIGHTING_SIZE) {
- fprintf(stderr, "newton: Default model material too big\n");
- my_exit(1);
- }
- default_model_material[n++] = f;
- }
- default_model_material_size = n;
- break;
-
- case 'W':
- p = line + 1;
- for (n = 0; sscanf(p, "%f%n", &f, &q) == 1; p += q) {
- if (n == MAX_LIGHTING_SIZE) {
- fprintf(stderr, "newton: Wall material too big\n");
- my_exit(1);
- }
- wall_material[n++] = f;
- }
- wall_material_size = n;
- break;
-
- default:
- fprintf(stderr, "newton: Syntax error in config file: \"%s\"\n", line);
- my_exit(1);
- }
- }
-
- #endif /* CONFIG_FILE */
-
-
-
- rotate_graphics(Angle alpha,char axis)
- {
- /* adjust M */
- pushmatrix();
- loadmatrix(ident_matrix);
- rotate(alpha, axis);
- multmatrix(M);
- getmatrix(M);
- popmatrix();
-
- /* adjust M inverse */
- pushmatrix();
- loadmatrix(M_inv);
- rotate(-alpha, axis);
- getmatrix(M_inv);
- popmatrix();
-
- new_M = 1;
-
- /* set the light vector */
- apply(light_vec_M, light_vec_V, M_inv);
- }
-
-
- draw_everything()
- {
- swapbuffers();
-
- #ifdef HAS_CZCLEAR
- czclear(0, 0);
- #else /* HAS_CZCLEAR */
- if (mode == COLOR_MAP)
- color(BLACK);
- else
- RGBcolor(0, 0, 0);
- clear();
- zclear();
- #endif /* HAS_CZCLEAR */
-
- if (new_M) {
- loadmatrix(ident_matrix);
- lookat(0.,0.,DIST, 0.,0.,0., 0);
- multmatrix(M);
-
- new_M = 0;
- }
-
- draw_room();
- (*draw_model)();
- if (springs_too)
- draw_springs();
- }
-
-
- draw_room()
- {
- void (*actual_draw_wall)(int);
-
- if (mode == RGB)
- actual_draw_wall = draw_wall;
- else
- actual_draw_wall = draw_plain_wall;
-
- /* draw the wall surfaces */
- if (M[Y][Z] < HEIGHT/DIST)
- (*actual_draw_wall)(WALL_TOP);
-
- if (M[Y][Z] > -HEIGHT/DIST)
- (*actual_draw_wall)(WALL_BOTTOM);
-
- if (M[X][Z] < HEIGHT/DIST)
- (*actual_draw_wall)(WALL_RIGHT);
-
- if (M[X][Z] > -HEIGHT/DIST)
- (*actual_draw_wall)(WALL_LEFT);
-
- if (M[Z][Z] < HEIGHT/DIST)
- (*actual_draw_wall)(WALL_FRONT);
-
- if (M[Z][Z] > -HEIGHT/DIST)
- (*actual_draw_wall)(WALL_BACK);
-
- /* draw the frame itself */
- if (mode == COLOR_MAP)
- color(BLUE);
- else
- RGBcolor(50, 100, 255);
-
- #ifdef HAS_CZCLEAR
- zfunction(ZF_ALWAYS);
- #endif /* HAS_CZCLEAR */
-
- bgnline();
- v3f(wall[WALL_BOTTOM].surf_v[0]);
- v3f(wall[WALL_BOTTOM].surf_v[1]);
- v3f(wall[WALL_BOTTOM].surf_v[2]);
- v3f(wall[WALL_BOTTOM].surf_v[3]);
- v3f(wall[WALL_BOTTOM].surf_v[0]);
-
- v3f(wall[WALL_TOP].surf_v[0]);
- v3f(wall[WALL_TOP].surf_v[3]);
- v3f(wall[WALL_TOP].surf_v[2]);
- v3f(wall[WALL_TOP].surf_v[1]);
- v3f(wall[WALL_TOP].surf_v[0]);
- endline();
- bgnline();
- v3f(wall[WALL_BOTTOM].surf_v[1]);
- v3f(wall[WALL_TOP].surf_v[3]);
- endline();
- bgnline();
- v3f(wall[WALL_BOTTOM].surf_v[2]);
- v3f(wall[WALL_TOP].surf_v[2]);
- endline();
- bgnline();
- v3f(wall[WALL_BOTTOM].surf_v[3]);
- v3f(wall[WALL_TOP].surf_v[1]);
- endline();
-
- #ifdef HAS_CZCLEAR
- zfunction(ZF_GEQUAL);
- #endif /* HAS_CZCLEAR */
-
- }
-
-
- void
- draw_lighted_wall(int n)
- {
- struct wall *w = &wall[n];
- float e[3], pos[3], f_norm[4][3], vel_correction;
- float rotm[4][4], rotm_inv[4][4], cos_beta, sin_beta;
- int axis1, axis2, axis3;
- int t;
-
- lighting_on();
- lmbind(MATERIAL, WALL_MATERIAL_INDEX);
-
- axis1 = w->axis;
-
- if (w->penetrated) {
-
- /*
- * move pos slightly outward, to prevent annoying artifacts
- */
- pos[X] = w->atom->pos[X];
- pos[Y] = w->atom->pos[Y];
- pos[Z] = w->atom->pos[Z];
- pos[axis1] *= SURF_TOL;
-
- vel_correction = vel_factor * w->atom->vel[w->axis];
- if (vel_correction < 0)
- vel_correction = -vel_correction;
- pos[w->axis] += w->sign * vel_correction;
-
- /*
- * calculate the normals to each triangular face
- */
- vec_op(e, w->surf_v[0], -, pos);
- cross(f_norm[0], e, w->surf_e[0]);
- normalize(f_norm[0]);
-
- vec_op(e, w->surf_v[1], -, pos);
- cross(f_norm[1], e, w->surf_e[1]);
- normalize(f_norm[1]);
-
- vec_op(e, w->surf_v[2], -, pos);
- cross(f_norm[2], e, w->surf_e[2]);
- normalize(f_norm[2]);
-
- vec_op(e, w->surf_v[3], -, pos);
- cross(f_norm[3], e, w->surf_e[3]);
- normalize(f_norm[3]);
-
- /*
- * calculate the normals at the vertices
- */
- vec_op(w->surf_norm[0], f_norm[3], +, f_norm[0]);
- normalize(w->surf_norm[0]);
-
- vec_op(w->surf_norm[1], f_norm[0], +, f_norm[1]);
- normalize(w->surf_norm[1]);
-
- vec_op(w->surf_norm[2], f_norm[1], +, f_norm[2]);
- normalize(w->surf_norm[2]);
-
- vec_op(w->surf_norm[3], f_norm[2], +, f_norm[3]);
- normalize(w->surf_norm[3]);
-
- vec_op(w->surf_norm[4], f_norm[0], +, f_norm[1]);
- vec_op(w->surf_norm[4], w->surf_norm[4], +, f_norm[2]);
- vec_op(w->surf_norm[4], w->surf_norm[4], +, f_norm[3]);
- normalize(w->surf_norm[4]);
-
- /*
- * draw the triangles
- */
- bgnpolygon();
- n3f(w->surf_norm[0]); v3f(w->surf_v[0]);
- n3f(w->surf_norm[1]); v3f(w->surf_v[1]);
- n3f(w->surf_norm[4]); v3f(pos);
- endpolygon();
- bgnpolygon();
- n3f(w->surf_norm[1]); v3f(w->surf_v[1]);
- n3f(w->surf_norm[2]); v3f(w->surf_v[2]);
- n3f(w->surf_norm[4]); v3f(pos);
- endpolygon();
- bgnpolygon();
- n3f(w->surf_norm[2]); v3f(w->surf_v[2]);
- n3f(w->surf_norm[3]); v3f(w->surf_v[3]);
- n3f(w->surf_norm[4]); v3f(pos);
- endpolygon();
- bgnpolygon();
- n3f(w->surf_norm[3]); v3f(w->surf_v[3]);
- n3f(w->surf_norm[0]); v3f(w->surf_v[0]);
- n3f(w->surf_norm[4]); v3f(pos);
- endpolygon();
-
-
- draw_norm(w->surf_v[0], w->surf_norm[0]);
- draw_norm(w->surf_v[1], w->surf_norm[1]);
- draw_norm(w->surf_v[2], w->surf_norm[2]);
- draw_norm(w->surf_v[3], w->surf_norm[3]);
- draw_norm(pos, w->surf_norm[4]);
-
- if (shadows_too == 0)
- goto finale;
-
- /*
- * check if a shadow is cast on the triangles. The condition is that
- * the normal to the triangle has a positive component in the direction
- * of the light.
- */
- for (t = 0; t < 4; t++ )
- if (dot(light_vec_M, f_norm[t]) > 0.) {
-
- lighting_off();
-
- axis2 = (axis1 + 1) % 3;
- if (w->surf_v[t][axis2] != w->surf_v[(t+1)%4][axis2])
- axis2 = (axis1 + 2) % 3;
-
- axis3 = (X + Y + Z) - (axis1 + axis2);
-
- /*
- * the following code generates a rotation matrix
- * of beta degrees around axis3
- */
- cos_beta = dot(f_norm[t], w->real_norm);
- sin_beta = sqrt(1. - cos_beta * cos_beta);
- cross(e, f_norm[t], w->real_norm);
- if (e[axis3] < 0.)
- sin_beta = -sin_beta;
-
- memcpy(rotm, ident_matrix, 4 * 4 *sizeof(float));
- memcpy(rotm_inv, ident_matrix, 4 * 4 *sizeof(float));
- rotm[axis1][axis1] =
- rotm[axis2][axis2] =
- rotm_inv[axis1][axis1] =
- rotm_inv[axis2][axis2] = cos_beta;
- if (axis3 != Y)
- if (axis1 < axis2) {
- rotm[axis1][axis2] = sin_beta;
- rotm[axis2][axis1] = -sin_beta;
- rotm_inv[axis1][axis2] = -sin_beta;
- rotm_inv[axis2][axis1] = sin_beta;
- }
- else {
- rotm[axis2][axis1] = sin_beta;
- rotm[axis1][axis2] = -sin_beta;
- rotm_inv[axis2][axis1] = -sin_beta;
- rotm_inv[axis1][axis2] = sin_beta;
- }
- else /* axis3 is Y */
- if (axis1 < axis2) {
- rotm[axis1][axis2] = -sin_beta;
- rotm[axis2][axis1] = sin_beta;
- rotm_inv[axis1][axis2] = sin_beta;
- rotm_inv[axis2][axis1] = -sin_beta;
- }
- else {
- rotm[axis2][axis1] = -sin_beta;
- rotm[axis1][axis2] = sin_beta;
- rotm_inv[axis2][axis1] = sin_beta;
- rotm_inv[axis1][axis2] = -sin_beta;
- }
-
- /* need to rotate the light vector as well */
- apply(e, light_vec_M, rotm);
-
- w->shadow[axis1][axis1] = 0.;
- w->shadow[axis1][axis2] = - e[axis2] /
- e[axis1];
- w->shadow[axis1][axis3] = - e[axis3] /
- e[axis1];
- e[axis1] = w->atom->pos[axis1] * SHADOW_TOL;
- e[axis2] = w->atom->pos[axis2];
- e[axis3] = w->atom->pos[axis3];
- translate(
- e[X],
- e[Y],
- e[Z]
- );
- multmatrix(rotm_inv);
- multmatrix(w->shadow);
- multmatrix(rotm);
- translate(
- - w->atom->pos[X],
- - w->atom->pos[Y],
- - w->atom->pos[Z]
- );
-
- draw_shadows();
- }
-
- lighting_on();
- }
- else {
- bgnpolygon();
- n3f(w->real_norm);
- v3f(w->surf_v[0]);
- v3f(w->surf_v[1]);
- v3f(w->surf_v[2]);
- v3f(w->surf_v[3]);
- endpolygon();
-
-
- #ifdef HEDGEHOG
-
- axis2 = (axis1 + 1) % 3;
- axis3 = (axis1 + 2) % 3;
- e[axis1] = w->sign * HEIGHT;
- e[axis2] = e[axis3] = 0.;
- draw_norm(e, w->real_norm);
-
- #endif /* HEDGEHOG */
-
- if (shadows_too == 0)
- goto finale;
-
- /*
- * check if a shadow is cast on the wall. The condition is that
- * the normal to the wall has a positive component in the direction
- * of the light.
- */
- if (dot(light_vec_M, w->real_norm) > 0.) {
-
- axis2 = (axis1 + 1) % 3;
- axis3 = (axis1 + 2) % 3;
- lighting_off();
-
- w->shadow[axis1][axis1] = 0.;
- w->shadow[axis1][axis2] = - light_vec_M[axis2] /
- light_vec_M[axis1];
- w->shadow[axis1][axis3] = - light_vec_M[axis3] /
- light_vec_M[axis1];
-
- e[axis1] = w->sign * HEIGHT * SHADOW_TOL;
- e[axis2] = e[axis3] = 0.;
-
- translate(e[X], e[Y], e[Z]);
- multmatrix(w->shadow);
-
- e[axis1] = - w->sign * HEIGHT;
- translate(e[X], e[Y], e[Z]);
-
- draw_shadows();
-
- lighting_on();
- }
- }
-
-
- finale:
-
- hide_wall_exterior(n);
- }
-
-
- void
- draw_pinball_wall(int n)
- {
- struct wall *w = &wall[n];
- float pos[3];
- float basic_color[3], color[3];
-
- basic_color[0] = red2;
- basic_color[1] = green2;
- basic_color[2] = blue2;
-
- if (w->penetrated) {
- /*
- * calculate the colors
- */
- color[0] = red1 * w->depth + red2;
- if (color[0] > 1.0)
- color[0] = 1.0;
- color[1] = green1 * w->depth + green2;
- if (color[1] > 1.0)
- color[1] = 1.0;
- color[2] = blue1 * w->depth + blue2;
- if (color[2] > 1.0)
- color[2] = 1.0;
-
- /*
- * move pos slightly outward, to prevent annoying artifacts
- */
- pos[X] = w->atom->pos[X];
- pos[Y] = w->atom->pos[Y];
- pos[Z] = w->atom->pos[Z];
- pos[w->axis] *= SURF_TOL;
-
- /*
- * draw the triangles
- */
- bgnpolygon();
- c3f(basic_color); v3f(w->surf_v[0]);
- c3f(basic_color); v3f(w->surf_v[1]);
- c3f(color); v3f(pos);
- endpolygon();
- bgnpolygon();
- c3f(basic_color); v3f(w->surf_v[1]);
- c3f(basic_color); v3f(w->surf_v[2]);
- c3f(color); v3f(pos);
- endpolygon();
- bgnpolygon();
- c3f(basic_color); v3f(w->surf_v[2]);
- c3f(basic_color); v3f(w->surf_v[3]);
- c3f(color); v3f(pos);
- endpolygon();
- bgnpolygon();
- c3f(basic_color); v3f(w->surf_v[3]);
- c3f(basic_color); v3f(w->surf_v[0]);
- c3f(color); v3f(pos);
- endpolygon();
- }
- else {
- bgnpolygon();
- c3f(basic_color);
- v3f(w->surf_v[0]);
- v3f(w->surf_v[1]);
- v3f(w->surf_v[2]);
- v3f(w->surf_v[3]);
- endpolygon();
- }
-
- hide_wall_exterior(n);
- }
-
-
- void
- draw_plain_wall(int n)
- {
- struct wall *w = &wall[n];
- float pos[3];
-
- if (w->penetrated) {
- /*
- * move pos slightly outward, to prevent annoying artifacts
- */
- pos[X] = w->atom->pos[X] * SURF_TOL;
- pos[Y] = w->atom->pos[Y] * SURF_TOL;
- pos[Z] = w->atom->pos[Z] * SURF_TOL;
-
- /*
- * draw the triangles
- */
- bgnpolygon();
- color(GREY); v3f(w->surf_v[0]);
- color(GREY); v3f(w->surf_v[1]);
- color(GREY); v3f(pos);
- endpolygon();
- bgnpolygon();
- color(GREY); v3f(w->surf_v[1]);
- color(GREY); v3f(w->surf_v[2]);
- color(GREY); v3f(pos);
- endpolygon();
- bgnpolygon();
- color(GREY); v3f(w->surf_v[2]);
- color(GREY); v3f(w->surf_v[3]);
- color(GREY); v3f(pos);
- endpolygon();
- bgnpolygon();
- color(GREY); v3f(w->surf_v[3]);
- color(GREY); v3f(w->surf_v[0]);
- color(GREY); v3f(pos);
- endpolygon();
- }
- else {
- bgnpolygon();
- color(GREY);
- v3f(w->surf_v[0]);
- v3f(w->surf_v[1]);
- v3f(w->surf_v[2]);
- v3f(w->surf_v[3]);
- endpolygon();
- }
-
- hide_wall_exterior(n);
- }
-
-
- /*
- * hide the back side of the wall, so that the body is not seen
- * penetrating the wall
- */
- hide_wall_exterior(int n)
- {
- struct wall *w = &wall[n];
- float corner[4][3];
- int i, j;
-
- for (i = 0; i < 4; i++) {
- for (j = X; j <= Z; j++)
- corner[i][j] = w->surf_v[i][j];
- corner[i][w->axis] += w->sign * HEIGHT;
- }
-
- backbuffer(FALSE);
-
- bgnpolygon();
- v3f(w->surf_v[0]);
- v3f(corner[0]);
- v3f(corner[1]);
- v3f(w->surf_v[1]);
- endpolygon();
-
- bgnpolygon();
- v3f(w->surf_v[1]);
- v3f(corner[1]);
- v3f(corner[2]);
- v3f(w->surf_v[2]);
- endpolygon();
-
- bgnpolygon();
- v3f(w->surf_v[2]);
- v3f(corner[2]);
- v3f(corner[3]);
- v3f(w->surf_v[3]);
- endpolygon();
-
- bgnpolygon();
- v3f(w->surf_v[3]);
- v3f(corner[3]);
- v3f(corner[0]);
- v3f(w->surf_v[0]);
- endpolygon();
-
- backbuffer(TRUE);
- }
-
-
-
- void
- lighting_off()
- {
- if (lighting == 0)
- return;
-
- lmbind(MATERIAL, 0);
- lmbind(LMODEL, 0);
- lmbind(LIGHT0, 0);
-
- mmode(MSINGLE);
- loadmatrix(ident_matrix);
- perspective(400, 5./4., DIST - RADIUS, DIST + RADIUS);
- lookat(0.,0.,DIST, 0.,0.,0., 0);
-
- multmatrix(M);
-
- lighting = 0;
- }
-
- void
- lighting_on()
- {
- if (lighting == 1)
- return;
-
-
- #ifdef CLOVER1 /* 4D gl bug */
- loadmatrix(ident_matrix);
- #endif /* CLOVER1 */
-
- mmode(MVIEWING);
- loadmatrix(ident_matrix);
- perspective(400, 5./4., DIST - RADIUS, DIST + RADIUS);
- lookat(0.,0.,DIST, 0.,0.,0., 0);
-
- lmbind(LIGHT0, 1);
- lmbind(LMODEL, 1);
-
- multmatrix(M);
-
- lighting = 1;
- }
-
-
- draw_shadows()
- {
- Surf *sp;
- int i;
-
- zwritemask(0);
-
- setpattern(HALFTONE);
-
- if (mode == COLOR_MAP)
- color(BLACK);
- else
- RGBcolor(0, 0, 0);
-
- for (sp = model_surfs; sp < end_model_surfs TOTAL; sp++) {
-
- bgnpolygon();
-
- for (i = 0; i < sp->n; i++)
- v3f((sp->vert[i])->pos);
-
- endpolygon();
- }
-
- setpattern(0);
-
- zwritemask(0xffffff);
- }
-
-
- void
- draw_flat_surfs()
- {
- float *v, *norm;
- Surf *sp;
- int i, n;
-
- /*
- * PHASE I: compute the normals
- */
- SLAVE_FUNC(DRAW_FLAT_SURFS_1);
- draw_flat_surfs_1(model_surfs, end_model_surfs MASTER);
- WAIT_FOR_SLAVE();
-
- /*
- * PHASE II: draw surfaces
- */
-
- #ifdef HAS_BLENDING
- if (alpha_blended) {
- blendfunction(BF_SA, BF_MSA);
- zwritemask(0);
- }
- #endif /* HAS_BLENDING */
-
- lmbind(MATERIAL, MODEL_MATERIAL_INDEX);
-
- for (sp = model_surfs; sp < end_model_surfs TOTAL; sp++) {
-
- n = sp->n;
-
- bgnpolygon();
-
- for (i = 0; i < n; i++) {
- v = (sp->vert[i])->pos;
- norm = &(sp->norm)[4*i];
-
- n3f(norm);
- v3f(v);
- }
-
- endpolygon();
-
- #ifdef HEDGEHOG
- for (i = 0; i < n; i++) {
- v = (sp->vert[i])->pos;
- norm = &(sp->norm)[4*i];
- draw_norm(v, norm);
- }
- #endif /* HEDGEHOG */
- }
-
- #ifdef HAS_BLENDING
- if (alpha_blended) {
- blendfunction(BF_ONE, BF_ZERO);
- zwritemask(0xffffff);
- }
- #endif /* HAS_BLENDING */
-
- }
-
-
- draw_flat_surfs_1(Surf *start, Surf *finish)
- {
- float *v, *nv, *e1, *e2, *tmp, buf[2][3], *norm;
- Surf *sp;
- int i, n;
-
- e1 = &buf[0][0];
- e2 = &buf[1][0];
-
- for (sp = start; sp < finish; sp++) {
-
- n = sp->n;
-
- v = (sp->vert[0])->pos;
- vec_op(e1, v, -, (sp->vert[n-1])->pos);
-
- for (i = 1; i < n; i++) {
- nv = (sp->vert[i])->pos;
- norm = &sp->norm[4*i];
-
- vec_op(e2, nv, -, v);
- cross(norm, e1, e2);
- normalize(norm);
-
- tmp = e1; e1 = e2; e2 = tmp;
- v = nv;
- }
-
- nv = (sp->vert[0])->pos;
- norm = &sp->norm[0];
- vec_op(e2, nv, -, v);
- cross(norm, e1, e2);
- normalize(norm);
- }
- }
-
-
- void
- draw_smooth_surfs()
- {
- Surf *sp;
- Atom **p;
- int n;
-
- /*
- * PHASE I: clear all normals
- */
- SLAVE_FUNC(DRAW_SMOOTH_SURFS_1);
- draw_smooth_surfs_1(model_atoms, end_model_atoms MASTER);
- WAIT_FOR_SLAVE();
-
- /*
- * PHASE II: accumulate for each atom all the normals to the surfaces
- * it participates in
- */
- SLAVE_FUNC(DRAW_SMOOTH_SURFS_2);
- draw_smooth_surfs_2(model_surfs, end_model_surfs MASTER MASTER_PARAM);
- WAIT_FOR_SLAVE();
-
- /*
- * PHASE III: normalize the cumulative normals
- */
- SLAVE_FUNC(DRAW_SMOOTH_SURFS_3);
- draw_smooth_surfs_3(model_atoms, end_model_atoms MASTER);
- WAIT_FOR_SLAVE();
-
- /*
- * PHASE IV: draw the surfaces
- */
-
- #ifdef HAS_BLENDING
- if (alpha_blended) {
- blendfunction(BF_SA, BF_MSA);
- zwritemask(0);
- }
- #endif /* HAS_BLENDING */
-
- lmbind(MATERIAL, MODEL_MATERIAL_INDEX);
-
- for (sp = model_surfs; sp < end_model_surfs TOTAL; sp++) {
-
- n = sp->n;
-
- bgnpolygon();
-
- for (p = &sp->vert[0]; p < &sp->vert[n]; p++) {
- n3f((*p)->norm MASTER);
- v3f((*p)->pos);
- }
-
- endpolygon();
-
- #ifdef HEDGEHOG
- for (p = &sp->vert[0]; p < &sp->vert[n]; p++)
- draw_norm((*p)->pos, (*p)->norm MASTER);
- #endif /* HEDGEHOG */
- }
-
- #ifdef HAS_BLENDING
- if (alpha_blended) {
- blendfunction(BF_ONE, BF_ZERO);
- zwritemask(0xffffff);
- }
- #endif /* HAS_BLENDING */
-
- }
-
-
- draw_smooth_surfs_1(Atom *start, Atom *finish)
- {
- Atom *ap;
-
- for (ap = start; ap < finish; ap++) {
-
- #ifdef MP
-
- {
- int i;
-
- for (i = 1; i < nproc; i++)
- ap->norm [i] [X] =
- ap->norm [i] [Y] =
- ap->norm [i] [Z] = 0.;
- }
-
- #endif /* MP */
-
- ap->norm MASTER [X] =
- ap->norm MASTER [Y] =
- ap->norm MASTER [Z] = 0.;
- }
- }
-
-
- draw_smooth_surfs_2(Surf *start, Surf *finish, CPU_PARAM_TYPE)
- {
- float *v, *nv, *e1, *e2, *tmp, buf[2][3], norm[3];
- Surf *sp;
- Atom **p;
- int n;
-
- e1 = &buf[0][0];
- e2 = &buf[1][0];
-
- for (sp = start; sp < finish; sp++) {
-
- n = sp->n;
-
- v = (sp->vert[0])->pos;
- vec_op(e1, v, -, (sp->vert[n-1])->pos);
-
- for (p = &sp->vert[1]; p < &sp->vert[n]; p++) {
- nv = (*p)->pos;
- vec_op(e2, nv, -, v);
- cross(norm, e1, e2);
- normalize(norm);
-
- vec_op(p[-1]->norm CPU, p[-1]->norm CPU, +, norm);
-
- tmp = e1; e1 = e2; e2 = tmp;
- v = nv;
- }
-
- nv = (sp->vert[0])->pos;
- vec_op(e2, nv, -, v);
- cross(norm, e1, e2);
- normalize(norm);
-
- vec_op(p[-1]->norm CPU, p[-1]->norm CPU, +, norm);
- }
- }
-
-
- draw_smooth_surfs_3(Atom *start, Atom *finish)
- {
- Atom *ap;
-
- for (ap = start; ap < finish; ap++) {
-
- #ifdef MP
-
- {
- int i;
-
- for (i = 1; i < nproc; i++)
- vec_op(ap->norm MASTER,
- ap->norm MASTER, +, ap->norm[i]);
- }
-
- #endif /* MP */
-
- normalize(ap->norm MASTER);
- }
- }
-
-
- void
- draw_springs()
- {
- Spring *spring;
-
- if (mode == COLOR_MAP)
- color(YELLOW);
- else
- RGBcolor(200, 200, 20);
-
- for (spring = model_springs; spring < end_model_springs TOTAL; spring++) {
- bgnline();
- v3f(spring->from->pos);
- v3f(spring->to->pos);
- endline();
- }
- }
-